package com.dymall.user.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dymall.common.exception.BadRequestException;
import com.dymall.common.utils.BeanUtils;
import com.dymall.common.utils.CollUtils;
import com.dymall.common.utils.UserContext;
import com.dymall.user.domain.dto.AddressDTO;
import com.dymall.user.domain.po.Address;
import com.dymall.user.mapper.AddressMapper;
import com.dymall.user.service.AddressService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class AddressServiceImpl extends ServiceImpl<AddressMapper, Address> implements AddressService {
    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public List<AddressDTO> findMyAddresses() {
        // 1、从redis中查询当前用户地址列表缓存
        String key = "addresses:" + UserContext.getUser();
        String addresses = stringRedisTemplate.opsForValue().get(key);
        if(StrUtil.isNotBlank(addresses)){
            // 2、存在，直接返回
            return JSONUtil.toList(addresses, AddressDTO.class);
        }
        // 3、不存在
        // 3.1、检验是否是空值"" —— 防范缓存穿透
        if(addresses != null){
            return CollUtils.emptyList();
        }
        // 3.2、不为空值，查询数据库
        List<Address> list = lambdaQuery().eq(Address::getUserId, UserContext.getUser()).list();
        if(list == null || list.isEmpty()){
            // 4、不存在
            // 4.1、将空值写入redis，防范缓存穿透
            stringRedisTemplate.opsForValue().set(key, "", 2, TimeUnit.MINUTES);
            // 4.2、返回空列表
            return CollUtils.emptyList();
        }
        List<AddressDTO> result = BeanUtils.copyList(list, AddressDTO.class);
        //4、存在，写入redis
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(result), 10, TimeUnit.MINUTES);
        return result;
    }

    @Override
    public AddressDTO findAddressById(Long id) {
        // 1、从redis中查询
        String key = "address:" + id;
        String addressDTO = stringRedisTemplate.opsForValue().get(key);
        if(StrUtil.isNotBlank(addressDTO)){
            // 2、存在，直接返回
            return JSONUtil.toBean(addressDTO, AddressDTO.class);
        }
        // 3、不存在
        // 3.1、检验是否为空值""
        if(addressDTO != null){
            throw new BadRequestException("该id的地址不存在");
        }
        //3.2、不为空值，查询数据库
        Address address = getById(id);
        if(address == null){
            // 3.3、将空值写入redis，防范缓存穿透
            stringRedisTemplate.opsForValue().set(key, "", 2, TimeUnit.MINUTES);
            throw new BadRequestException("该id的地址不存在");
        }
        Long userId = UserContext.getUser();
        if(address.getUserId().equals(userId)){
            throw new BadRequestException("地址不属于当前登录用户");
        }
        AddressDTO result = BeanUtils.copyBean(address, AddressDTO.class);
        // 4、存在，写入redis
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(result), 10, TimeUnit.MINUTES);
        return result;
    }
}
